﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using RabbitMQ.Client;
using RabbitMQ.Client.Framing;

namespace HYService.RabbitMQ
{
    public partial class RabbitHub
    {
        private static BasicProperties BuildDelayHeaders(long deferMilliseconds)
        {
            BasicProperties props = new BasicProperties();
            props.Headers = new Dictionary<string, object>();
            props.Headers.Add("x-delay", deferMilliseconds);
            return props;
        }

        private static void SetProperties(ref IBasicProperties props)
        {
            if (props == null)
            {
                props = new BasicProperties();
                props.ContentType = "text/plain";
                props.DeliveryMode = 2;
            }
        }

        #region 广播消息
        /// <summary>
        /// 发布一条广播消息
        /// </summary>
        /// <typeparam name="T">消息体类型</typeparam>
        /// <param name="exchange">交换机名称</param>
        /// <param name="message">消息体实例</param>
        /// <param name="props">发送配置项</param>
        /// <param name="onBeforeSending">消息发送前的配置委托</param>
        /// <param name="onAfterSending">消息发送后的配置委托</param>
        public static void Broadcast<T>(string exchange, T message, IBasicProperties props = null, Action<IModel> onBeforeSending = null, Action<IModel> onAfterSending = null) where T : class
        {
            try
            {
                using (var connection = RabbitBus.CreateConnection())
                {
                    using (var channel = connection.CreateModel())
                    {
                        if (onBeforeSending != null)
                        {
                            onBeforeSending(channel);
                        }

                        RabbitHub.SetProperties(ref props);
                        var json = JsonConvert.SerializeObject(message);
                        var bytes = Encoding.UTF8.GetBytes(json);
                        channel.BasicPublish(exchange, "", props, bytes);

                        if (onAfterSending != null)
                        {
                            onAfterSending(channel);
                        }
                    }
                }
            }
            catch
            {

            }
        }

        /// <summary>
        /// 发布多条广播消息
        /// </summary>
        /// <typeparam name="T">消息体类型</typeparam>
        /// <param name="exchange">交换机名称</param>
        /// <param name="messages">消息体集合</param>
        /// <param name="props">发送配置项</param>
        /// <param name="onBeforeSending">消息发送前的配置委托</param>
        /// <param name="onAfterSending">消息发送后的配置委托</param>
        public static void Broadcast<T>(string exchange, IEnumerable<T> messages, IBasicProperties props = null, Action<IModel> onBeforeSending = null, Action<IModel> onAfterSending = null) where T : class
        {
            try
            {
                using (var connection = RabbitBus.CreateConnection())
                {
                    using (var channel = connection.CreateModel())
                    {
                        if (onBeforeSending != null)
                        {
                            onBeforeSending(channel);
                        }

                        RabbitHub.SetProperties(ref props);

                        foreach (var message in messages)
                        {
                            try
                            {
                                var json = JsonConvert.SerializeObject(message);
                                var bytes = Encoding.UTF8.GetBytes(json);
                                channel.BasicPublish(exchange, "", props, bytes);
                            }
                            catch
                            {
                                continue;
                            }
                        }

                        if (onAfterSending != null)
                        {
                            onAfterSending(channel);
                        }
                    }
                }
            }
            catch
            {

            }
        }

        /// <summary>
        /// 发布一条广播消息
        /// </summary>
        /// <typeparam name="T">消息体类型</typeparam>
        /// <param name="exchange">交换机名称</param>
        /// <param name="message">消息体实例</param>
        /// <param name="deferMilliseconds">消息延迟时间(毫秒)</param>
        /// <param name="onBeforeSending">消息发送前的配置委托</param>
        /// <param name="onAfterSending">消息发送后的配置委托</param>
        public static void Broadcast<T>(string exchange, T message, long deferMilliseconds, Action<IModel> onBeforeSending = null, Action<IModel> onAfterSending = null) where T : class
        {
            try
            {
                using (var connection = RabbitBus.CreateConnection())
                {
                    using (var channel = connection.CreateModel())
                    {
                        if (onBeforeSending != null)
                        {
                            onBeforeSending(channel);
                        }

                        var props = RabbitHub.BuildDelayHeaders(deferMilliseconds);

                        var json = JsonConvert.SerializeObject(message);
                        var bytes = Encoding.UTF8.GetBytes(json);
                        channel.BasicPublish(exchange, "", props, bytes);

                        if (onAfterSending != null)
                        {
                            onAfterSending(channel);
                        }
                    }
                }
            }
            catch
            {

            }
        }

        /// <summary>
        /// 发布多条广播消息
        /// </summary>
        /// <typeparam name="T">消息体类型</typeparam>
        /// <param name="exchange">交换机名称</param>
        /// <param name="messages">消息体集合</param>
        /// <param name="deferMilliseconds">消息延迟时间(毫秒)</param>
        /// <param name="onBeforeSending">消息发送前的配置委托</param>
        /// <param name="onAfterSending">消息发送后的配置委托</param>
        public static void Broadcast<T>(string exchange, IEnumerable<T> messages, long deferMilliseconds, Action<IModel> onBeforeSending = null, Action<IModel> onAfterSending = null) where T : class
        {
            try
            {
                using (var connection = RabbitBus.CreateConnection())
                {
                    using (var channel = connection.CreateModel())
                    {
                        if (onBeforeSending != null)
                        {
                            onBeforeSending(channel);
                        }

                        var props = RabbitHub.BuildDelayHeaders(deferMilliseconds);

                        foreach (var message in messages)
                        {
                            try
                            {
                                var json = JsonConvert.SerializeObject(message);
                                var bytes = Encoding.UTF8.GetBytes(json);
                                channel.BasicPublish(exchange, "", props, bytes);
                            }
                            catch
                            {
                                continue;
                            }
                        }

                        if (onAfterSending != null)
                        {
                            onAfterSending(channel);
                        }
                    }
                }
            }
            catch
            {

            }
        }
        #endregion

        #region 定向消息
        /// <summary>
        /// 发送定向消息
        /// </summary>
        /// <typeparam name="T">消息体类型</typeparam>
        /// <param name="queue">队列名称</param>
        /// <param name="message">消息体</param>
        /// <param name="props">发送配置项</param>
        /// <param name="onBeforeSending">消息发送前的配置委托</param>
        /// <param name="onAfterSending">消息发送后的配置委托</param>
        public static void Send<T>(string queue, T message, IBasicProperties props = null, Action<IModel> onBeforeSending = null, Action<IModel> onAfterSending = null) where T : class
        {
            try
            {
                using (var connection = RabbitBus.CreateConnection())
                {
                    using (var channel = connection.CreateModel())
                    {
                        if (onBeforeSending != null)
                        {
                            onBeforeSending(channel);
                        }

                        RabbitHub.SetProperties(ref props);
                        var json = JsonConvert.SerializeObject(message);
                        var bytes = Encoding.UTF8.GetBytes(json);
                        channel.BasicPublish("", queue, props, bytes);

                        if (onAfterSending != null)
                        {
                            onAfterSending(channel);
                        }
                    }
                }
            }
            catch
            {

            }
        }

        /// <summary>
        /// 发送多条定向消息
        /// </summary>
        /// <typeparam name="T">消息体类型</typeparam>
        /// <param name="queue">队列名称</param>
        /// <param name="messages">消息体集合</param>
        /// <param name="props">发送配置项</param>
        /// <param name="onBeforeSending">消息发送前的配置委托</param>
        /// <param name="onAfterSending">消息发送后的配置委托</param>
        public static void Send<T>(string queue, IEnumerable<T> messages, IBasicProperties props = null, Action<IModel> onBeforeSending = null, Action<IModel> onAfterSending = null) where T : class
        {
            try
            {
                using (var connection = RabbitBus.CreateConnection())
                {
                    using (var channel = connection.CreateModel())
                    {
                        if (onBeforeSending != null)
                        {
                            onBeforeSending(channel);
                        }

                        RabbitHub.SetProperties(ref props);

                        foreach (var message in messages)
                        {
                            try
                            {
                                var json = JsonConvert.SerializeObject(message);
                                var bytes = Encoding.UTF8.GetBytes(json);
                                channel.BasicPublish("", queue, props, bytes);
                            }
                            catch
                            {
                                continue;
                            }
                        }

                        if (onAfterSending != null)
                        {
                            onAfterSending(channel);
                        }
                    }
                }
            }
            catch
            {

            }
        }

        /// <summary>
        /// 发送定向消息
        /// </summary>
        /// <typeparam name="T">消息体类型</typeparam>
        /// <param name="queue">队列名称</param>
        /// <param name="message">消息体</param>
        /// <param name="deferMilliseconds">消息延迟时间(毫秒)</param>
        /// <param name="onBeforeSending">消息发送前的配置委托</param>
        /// <param name="onAfterSending">消息发送后的配置委托</param>
        public static void Send<T>(string queue, T message, long deferMilliseconds, Action<IModel> onBeforeSending = null, Action<IModel> onAfterSending = null) where T : class
        {
            try
            {
                using (var connection = RabbitBus.CreateConnection())
                {
                    using (var channel = connection.CreateModel())
                    {
                        if (onBeforeSending != null)
                        {
                            onBeforeSending(channel);
                        }

                        var props = RabbitHub.BuildDelayHeaders(deferMilliseconds);

                        var json = JsonConvert.SerializeObject(message);
                        var bytes = Encoding.UTF8.GetBytes(json);
                        channel.BasicPublish("", queue, props, bytes);

                        if (onAfterSending != null)
                        {
                            onAfterSending(channel);
                        }
                    }
                }
            }
            catch
            {

            }
        }

        /// <summary>
        /// 发送多条定向消息
        /// </summary>
        /// <typeparam name="T">消息体类型</typeparam>
        /// <param name="queue">队列名称</param>
        /// <param name="messages">消息体集合</param>
        /// <param name="deferMilliseconds">消息延迟时间(毫秒)</param>
        /// <param name="onBeforeSending">消息发送前的配置委托</param>
        /// <param name="onAfterSending">消息发送后的配置委托</param>
        public static void Send<T>(string queue, IEnumerable<T> messages, long deferMilliseconds, Action<IModel> onBeforeSending = null, Action<IModel> onAfterSending = null) where T : class
        {
            try
            {
                using (var connection = RabbitBus.CreateConnection())
                {
                    using (var channel = connection.CreateModel())
                    {
                        if (onBeforeSending != null)
                        {
                            onBeforeSending(channel);
                        }

                        var props = RabbitHub.BuildDelayHeaders(deferMilliseconds);

                        foreach (var message in messages)
                        {
                            try
                            {
                                var json = JsonConvert.SerializeObject(message);
                                var bytes = Encoding.UTF8.GetBytes(json);
                                channel.BasicPublish("", queue, props, bytes);
                            }
                            catch
                            {
                                continue;
                            }
                        }

                        if (onAfterSending != null)
                        {
                            onAfterSending(channel);
                        }
                    }
                }
            }
            catch
            {

            }
        }
        #endregion

        #region 路由消息
        /// <summary>
        /// 发送一条路由消息
        /// </summary>
        /// <typeparam name="T">消息体类型</typeparam>
        /// <param name="exchange">交换机名称</param>
        /// <param name="routingKey">路由键</param>
        /// <param name="message">消息体</param>
        /// <param name="props">发送配置项</param>
        /// <param name="onBeforeSending">消息发送前的配置委托</param>
        /// <param name="onAfterSending">消息发送后的配置委托</param>
        public static void Route<T>(string exchange, string routingKey, T message, IBasicProperties props = null, Action<IModel> onBeforeSending = null, Action<IModel> onAfterSending = null) where T : class
        {
            try
            {
                using (var connection = RabbitBus.CreateConnection())
                {
                    using (var channel = connection.CreateModel())
                    {
                        if (onBeforeSending != null)
                        {
                            onBeforeSending(channel);
                        }

                        RabbitHub.SetProperties(ref props);
                        var json = JsonConvert.SerializeObject(message);
                        var bytes = Encoding.UTF8.GetBytes(json);
                        channel.BasicPublish(exchange, routingKey, props, bytes);

                        if (onAfterSending != null)
                        {
                            onAfterSending(channel);
                        }
                    }
                }
            }
            catch
            {

            }
        }

        /// <summary>
        /// 发送多条路由消息
        /// </summary>
        /// <typeparam name="T">消息体类型</typeparam>
        /// <param name="exchange">交换机名称</param>
        /// <param name="routingKey">路由键</param>
        /// <param name="messages">消息体集合</param>
        /// <param name="props">发送配置项</param>
        /// <param name="onBeforeSending">消息发送前的配置委托</param>
        /// <param name="onAfterSending">消息发送后的配置委托</param>
        public static void Route<T>(string exchange, string routingKey, IEnumerable<T> messages, IBasicProperties props = null, Action<IModel> onBeforeSending = null, Action<IModel> onAfterSending = null) where T : class
        {
            try
            {
                using (var connection = RabbitBus.CreateConnection())
                {
                    using (var channel = connection.CreateModel())
                    {
                        if (onBeforeSending != null)
                        {
                            onBeforeSending(channel);
                        }

                        RabbitHub.SetProperties(ref props);

                        foreach (var message in messages)
                        {
                            try
                            {
                                var json = JsonConvert.SerializeObject(message);
                                var bytes = Encoding.UTF8.GetBytes(json);
                                channel.BasicPublish(exchange, "", props, bytes);
                            }
                            catch
                            {
                                continue;
                            }
                        }

                        if (onAfterSending != null)
                        {
                            onAfterSending(channel);
                        }
                    }
                }
            }
            catch
            {

            }
        }

        /// <summary>
        /// 发送一条路由消息
        /// </summary>
        /// <typeparam name="T">消息体类型</typeparam>
        /// <param name="exchange">交换机名称</param>
        /// <param name="routingKey">路由键</param>
        /// <param name="message">消息体</param>
        /// <param name="deferMilliseconds">消息延迟时间(毫秒)</param>
        /// <param name="onBeforeSending">消息发送前的配置委托</param>
        /// <param name="onAfterSending">消息发送后的配置委托</param>
        public static void Route<T>(string exchange, string routingKey, T message, long deferMilliseconds, Action<IModel> onBeforeSending = null, Action<IModel> onAfterSending = null) where T : class
        {
            try
            {
                using (var connection = RabbitBus.CreateConnection())
                {
                    using (var channel = connection.CreateModel())
                    {
                        if (onBeforeSending != null)
                        {
                            onBeforeSending(channel);
                        }

                        var props = RabbitHub.BuildDelayHeaders(deferMilliseconds);

                        var json = JsonConvert.SerializeObject(message);
                        var bytes = Encoding.UTF8.GetBytes(json);
                        channel.BasicPublish(exchange, routingKey, props, bytes);

                        if (onAfterSending != null)
                        {
                            onAfterSending(channel);
                        }
                    }
                }
            }
            catch
            {

            }
        }

        /// <summary>
        /// 发送多条路由消息
        /// </summary>
        /// <typeparam name="T">消息体类型</typeparam>
        /// <param name="exchange">交换机名称</param>
        /// <param name="routingKey">路由键</param>
        /// <param name="messages">消息体集合</param>
        /// <param name="deferMilliseconds">消息延迟时间(毫秒)</param>
        /// <param name="onBeforeSending">消息发送前的配置委托</param>
        /// <param name="onAfterSending">消息发送后的配置委托</param>
        public static void Route<T>(string exchange, string routingKey, IEnumerable<T> messages, long deferMilliseconds, Action<IModel> onBeforeSending = null, Action<IModel> onAfterSending = null) where T : class
        {
            try
            {
                using (var connection = RabbitBus.CreateConnection())
                {
                    using (var channel = connection.CreateModel())
                    {
                        if (onBeforeSending != null)
                        {
                            onBeforeSending(channel);
                        }

                        var props = RabbitHub.BuildDelayHeaders(deferMilliseconds);

                        foreach (var message in messages)
                        {
                            try
                            {
                                var json = JsonConvert.SerializeObject(message);
                                var bytes = Encoding.UTF8.GetBytes(json);
                                channel.BasicPublish(exchange, "", props, bytes);
                            }
                            catch
                            {
                                continue;
                            }
                        }

                        if (onAfterSending != null)
                        {
                            onAfterSending(channel);
                        }
                    }
                }
            }
            catch
            {

            }
        }
        #endregion
    }
}
